/*
Nathan Laird
this was a program that i created to use arrays. i chose to animate a swarm of bees.

Modified by Adam Poppenheimer
*/

Boolean Left = false;
Boolean Right = false;
Boolean Up = false;
Boolean Down = false;
double Jet;
double xmouse;
double ymouse;
double[] planetx = {600, 200};
double[] planety = {350, 350};
//Sets the speed of the game
double pace = 500;
double cos;
double sin;
//*pointsMarked Control Variables*//
//Sets tbe number of points makePath tries to project into the future
int pointsMarked = 600;
//Array used to store marked points
double[][] marks = new double[pointsMarked][2];
//Sets how dense the marked points are
int pointsMarkedInterval = 5;
//Sets how many draw cycles it takes to refresh the orbital loop
int pointsMarkedTimer = 10;
//Timer that handles makePath function
int timer = 0;

int beeNums = 1;// Number of bees
int planetNum = 2; //Number of planets
beez[] swarm = new beez[beeNums];
Planet[] planets = new Planet[planetNum];
void setup() {
  size (1000,700);
  smooth();
  for (int i = 0; i < beeNums; i++) {
    swarm[i] = new beez (400, 350,15,0,random(255),random(255),random(255));
  }
  for(int i = 0; i < planetNum; i++){
    planets[i] = new Planet(planetx[i], planety[i], 50, 50);
  }
}
class beez {
  double x, y, xVel, yVel, bWidth, degree, r, g, b;// beez class

  //beez constructor
  beez ( double myX, double myY, double myWidth, double myHeight, double myR, double myG, double myB){
    x = myX;
    y =myY;
    bWidth =myWidth;
    degree = myHeight;
    r = myR;
    g = myG;
    b = myB;
    xVel = 0;
    yVel = 0;
  }
  void display(){// draws a bee given x, y, width, height, and color
    line((float)(x-(bWidth*cos)),(float)(y-(bWidth*sin)),(float)(x+(bWidth*cos)),(float)(y+(bWidth*sin)));
    rectMode(CENTER);
    rect((float)x,(float)y,10,10);
    rect(x+(bWidth*cos),y+(bWidth*sin),5,5);
  }
  
  void addToVel(double newX, double newY){
    xVel += newX;
    yVel += newY;
  }
  
  void movement(){// dictates how the bees move
    if(Up){
     yVel = yVel + sin*Jet;
     xVel = xVel + cos*Jet;
    }
    if(Down){
   //  yspeed= yspeed + pace; 
    }
      if(Left){
    degree = degree + .08;
    }
      if(Right){
     degree = degree - .08 ;
    }
    x=x+xVel;
    y=y+yVel;
    if ((x>width) ||(x<0)){x=200;}
    if ((y>height)||(y<0)){y=200;}
  }

}

//A class defining the Planet object
class Planet{
  //Object variables
  double x, y, w, h;
  
  //Constructor
  Planet(double xpos, double ypos, double planWidth, double planHeight){
    x = xpos;
    y = ypos;
    w = planWidth;
    h = planHeight;
  }
  
  //Takes a position in the world and calculates the effects of this planet's
  //Gravity on an object's velocity at that position. Returns an array
  //Containing the values added to the point's x and y velocity.
  double[] addGravity(double xpos, double ypos){
    double r = 0;
    double grav, xratio, yratio;
    double xdiff = this.x - xpos;
    double ydiff = this.y - ypos;
    r = sqrt( sq(xdiff) + sq(ydiff) );
    xratio = xdiff / r;
    yratio = ydiff / r;
    println(sin);
    grav = pace/(r*r);
    double[] retval = {grav*xratio, grav*yratio};
    return retval;
  }
  
  //Paints the planet onto the screen
  void paint(){
    rect(x, y, w, h);
  }
}


void keyReleased() {
  if(key == 'a'){
    Left = false;
  }
  if(key == 'd'){
    Right = false;
  }
  if(key == 'k'){
    Up = false;
    Jet = 0;
  }
  if(key == 's'){
    Down = false;
  }
}
void keyPressed() {
  if(key == 'a'){
    Left = true;
  }
  if(key == 'd'){
    Right = true;
  }
  if(key == 'k'){
    Up = true;
    Jet = .05;
  }
  if(key == 's'){
    Down = true;
  }
}
void draw(){
 
 
  timer = (++timer)%pointsMarkedTimer;
  background (0,167,24);
  for(int i = 0; i < beeNums; i++){   
    swarm[i].display();
    swarm[i].movement();
    //Adds the effects of each gravity well in planets[] to the given bee.
    for(int j = 0; j < planetNum; j++){
      double[] newVel = planets[j].addGravity(swarm[i].x, swarm[i].y);
      swarm[i].addToVel(newVel[0], newVel[1]);
    }
    if(timer == 0){
      makePath(swarm[i].x, swarm[i].y, swarm[i].xVel, swarm[i].yVel);
    }
    markPath();
  }
  for(int i = 0; i < planetNum; i++){
    planets[i].paint();
  }
 rect(xmouse,ymouse,10,10);
}

//Projects a given bee's path, given its current velocity, a certain disrtance
void makePath(double x, double y, double xVel, double yVel){
  for(int i = 0; i < pointsMarked; i++){
    for(int j = 0; j < planetNum; j++){
      double[] newVel = planets[j].addGravity(x, y);
      xVel += newVel[0];
      yVel += newVel[1];
    }
    x += xVel;
    y += yVel;
    if(i%pointsMarkedInterval == 0){
      marks[i][0] = x;
      marks[i][1] = y;
    }
  }
}
void mousePressed(){
 if(mouseButton == LEFT) Jet = .1;
 if(mouseButton ==RIGHT) Jet = .01;
  xmouse=mouseX;
  ymouse=mouseY;
  Up = true;
  sin =-(swarm[0].y-ymouse)/sqrt(sq(swarm[0].x-xmouse)+sq(swarm[0].y-ymouse));
  cos =-(swarm[0].x-xmouse)/sqrt(sq(swarm[0].x-xmouse)+sq(swarm[0].y-ymouse));
}

void mouseMoved(){
  xmouse=mouseX;
  ymouse=mouseY;
sin =-(swarm[0].y-ymouse)/sqrt(sq(swarm[0].x-xmouse)+sq(swarm[0].y-ymouse));
 cos =-(swarm[0].x-xmouse)/sqrt(sq(swarm[0].x-xmouse)+sq(swarm[0].y-ymouse));
println(cos);
}

void mouseReleased(){
Up = false;
Jet = 0;
} 
void mouseDragged(){
xmouse = mouseX;
ymouse = mouseY;
sin =-(swarm[0].y-ymouse)/sqrt(sq(swarm[0].x-xmouse)+sq(swarm[0].y-ymouse));
 cos =-(swarm[0].x-xmouse)/sqrt(sq(swarm[0].x-xmouse)+sq(swarm[0].y-ymouse));
//rect(xmouse,ymouse,10,10);
}  

void markPath(){
  for(int i = 0; i < pointsMarked; i += pointsMarkedInterval){
    rect(marks[i][0], marks[i][1], 2, 2);
  }
}

